home *** CD-ROM | disk | FTP | other *** search
/ Info-Mac 4 / Info_Mac IV CD-ROM (Pacific HiTech Inc.)(August 1994).iso / Development / Source / Telnet 2.6.1d1 4⁄26⁄94 Folder / source / ftp / ftpbin.c < prev    next >
Text File  |  1994-04-13  |  60KB  |  1,908 lines

  1. /*
  2. *  User FTP
  3. *  6/8/87
  4. *****************************************************************
  5. *    NCSA Telnet for the Macintosh                                *
  6. *                                                                *
  7. *    National Center for Supercomputing Applications                *
  8. *    Software Development Group                                    *
  9. *    152 Computing Applications Building                            *
  10. *    605 E. Springfield Ave.                                        *
  11. *    Champaign, IL  61820                                        *
  12. *                                                                *
  13. *    Copyright (c) 1986-1992,                                    *
  14. *    Board of Trustees of the University of Illinois                *
  15. *****************************************************************
  16. */
  17.  
  18. #ifdef MPW
  19. #pragma segment FTPClient
  20. #endif
  21.  
  22. #include <stdio.h>
  23. #include <stdlib.h>
  24. #include <string.h>
  25. #include <ctype.h>
  26.  
  27. #include "TelnetHeader.h"
  28. #include "wind.h"
  29. #include "netevent.proto.h"
  30. #include "InternalEvents.h"
  31. #include "VSkeys.h"
  32.  
  33. #include "network.proto.h"
  34. #include "mydnr.proto.h"
  35. #include "bkgr.proto.h"
  36. #include "maclook.proto.h"
  37.  
  38. #include "vsdata.h"
  39. #include "vsinterf.proto.h"
  40.  
  41. #include "menuseg.proto.h"
  42. #include "rsmac.proto.h"
  43. #include "macbinary.h"
  44. #include "macutil.proto.h"
  45. #include "binsubs.proto.h"
  46. #include "ftppi.h"                                           /* list of commands, help strings */
  47. #include "ftpbin.proto.h"
  48. #include "parse.proto.h"
  49. #include "maclook.proto.h"
  50. #include "netevent.proto.h"
  51. #include "debug.h"
  52. #include "Connections.proto.h"
  53.  
  54. //#define    DEBUG_FTPCLIENT
  55. #ifdef    DEBUG_FTPCLIENT
  56. #define    ftpclient_debug_print(x) putln(x)
  57. #else
  58. #define ftpclient_debug_print(x)
  59. #endif
  60.  
  61.  
  62. #define FASCII 0
  63. #define FIMAGE 1                                           /* This is different than the definition
  64.                                                               in bkgr.c */
  65. #define FAMODE 0
  66. #define FIMODE 1
  67. //#define FMMODE 2                                           /* Mac Binary, when ready */
  68.  
  69. #define HFTP  21
  70.  
  71. #define SUCCESS       2
  72. #define ERROR      -1
  73. #define NONE      -2
  74. #define ABORT      -3
  75. #define INCOMPLETE -4
  76. #define AMBIGUOUS -5
  77. #define HAVEDATA   4
  78.  
  79. #define BUFFERS 8000                                       /* size of buffer */
  80. #define PATHLEN 256
  81. #define READSIZE 128                                       /* how much to read */
  82.  
  83. #define HELPRESID 23229
  84.  
  85. long
  86.         filelen = 0,                                       /* file transfer length */
  87.         start = 0L,                                           /* timing var */
  88.         towrite = 0,                                       /* file transfer pointer */
  89.         translen = 0,                                       /* length of file transfered */
  90.         transtime;
  91.  
  92. short
  93.         xp = 0,                                               /* general pointer */
  94.         ftpfh,                                               /* file handle for ftp */
  95.         fcnt = 0,                                           /* counter for ftpd */
  96.         ftpfilemode = 0,                                   /* file open mode for transfer */
  97.         hash = 0,                                           /* hash mark printing */
  98.         sendport = 1,                                       /* to send ports or not */
  99.         verbose = 1,                                       /* informative messages */
  100.         bell = 0,                                           /* sound bell */
  101.         autologin = 1,                                       /* login on connect */
  102.         prompt = 1,                                           /* check on multiple commands */
  103.         glob = 1,                                           /* expand wildcards */
  104.         slashflip = 1,                                       /* change \ to / */
  105.         fromtty = 1;                                       /* default input from tty */
  106.  
  107. char    Template[256];
  108. CInfoPBRec    ClientDirectoryState;
  109.  
  110. static short ftpdata;
  111. static char bellchar = {7};
  112. static char backspace = {8};
  113. static char poundsign = {'#'};
  114.  
  115. FILE*    fromfp = NULL;                        /* file pointer for input */
  116. MBFile*    ftp_mbfp;
  117.  
  118. unsigned char
  119.        *captlist = 0L, *newfile = 0L, *transfile = 0L,       /* name of file being sent/received */
  120.        *xs = 0L;                                           /* response string */
  121. unsigned short curftpprt = 0;                                   /* port to use */
  122. char    response_data[20][4];                               /* BYU 2.4.12 - first 4 characters of
  123.                                                               each response */
  124. unsigned char response_count[20];                           /* BYU 2.4.12 - non-zero indicates
  125.                                                               waiting for response */
  126.  
  127. extern short scrn;
  128. extern WindRec *screens;
  129.  
  130. #define RCPSEGSIZE 512
  131. #define O_RAW O_RDONLY
  132. #define EOLCHAR 13
  133. #define captlistsize 2001L
  134.  
  135. void    FTPClientunload(void) {}
  136.  
  137. /* putstring: display string using vt100 emulation routines                */
  138. void    putstring (short ftpscrn, char *string)
  139. {
  140.     for (; *string; string++)
  141.         parse (&screens[ftpscrn], (unsigned char *) string, 1);
  142. }
  143.  
  144. char   *stpblkp (char *mystring)
  145. {
  146.     /* Return pointer to first non blank in string */
  147.     short    mycnt;
  148.     char    *ptr;
  149.  
  150.     mycnt = 0;
  151.     ptr = mystring;
  152.     while (((*ptr == ' ') || (*ptr == '\t')) && (mycnt < 256)) {
  153.         ptr++;
  154.         mycnt++;
  155.     }
  156.     return (ptr);
  157. }
  158.  
  159. char   *stptok (char *mystring, char *myword, short mylen, char *myterms)
  160. {
  161.     /* Return pointer to first non blank in string */
  162.     short    done, i;
  163.     char    *p, *q;
  164.  
  165.     p = stpblkp (mystring);                                   /* skip leading blanks */
  166.     i = 0;
  167.     done = 0;
  168.     while (*(p + i) && (i <= mylen) && (done == 0)) {
  169.         q = myterms;
  170.         while ((*q) && (*q != *(p + i)))
  171.             q++;
  172.         if (!(*q)) {
  173.             *(myword + i) = *(p + i);
  174.             i++;
  175.         }
  176.         else
  177.             done = 1;
  178.     }
  179.     *(myword + i) = '\0';
  180.     q = p + i;
  181.     return (q);
  182. }
  183.  
  184. short ftpopen(Str255 name)
  185. {
  186.     OSErr    myerr;
  187.     short    myrefnum;
  188.     
  189.     myerr = HOpen (TelInfo->FTPClientVRefNum, TelInfo->FTPClientDirID, name, fsRdWrPerm, &myrefnum);
  190.     return (myrefnum);
  191. }
  192.  
  193. /* End of Macintosh Routines created at BYU, 1988 */
  194.  
  195. /*    ftpgets - read a line from the keyboard 
  196.     returns ABORT if aborted, non-zero on success */
  197.  
  198. char    ftpgets (char *s, short lim, short echo)
  199. //char   *s;                                    /* where to put the line */
  200. //short   lim, echo;                            /* max chars to read, echo? */
  201. {
  202.     int            count, i;
  203.     unsigned    char c;
  204.     char        *save;
  205.     Boolean        gotOne;                                           /* Did we get an event */
  206.     EventRecord    myEvent;                                   /* Event Record for this loop */
  207.  
  208.     count = 0;                                               /* none read */
  209.     save = s;                                               /* beginning of line */
  210.  
  211.     while (1) {
  212.  
  213.         gotOne = WaitNextEvent (everyEvent, &myEvent, gApplicationPrefs->TimeSlice, 0L);
  214.  
  215.         if ((myEvent.what == keyDown) || (myEvent.what == autoKey))
  216.             c = myEvent.message & charCodeMask;
  217.         else {
  218.             Stask ();                                       /* BYU 2.4.15 */
  219.             DoNetEvents ();                                   /* process event queue */
  220.             c = 0;
  221.         }
  222.  
  223.         switch (c) {                                       /* allow certain editing chars */
  224.         case 8:                                           /* backspace */
  225.             if (count) {
  226.                 if (echo) {
  227.                     parse (&screens[scrn], &c, 1);
  228.                     parse (&screens[scrn], (unsigned char *) " ", 1);
  229.                     parse (&screens[scrn], &c, 1);
  230.                 }
  231.                 count--;                                   /* one less character */
  232.                 s--;                                       /* move pointer backward */
  233.             }
  234.             break;
  235.         case 13:                                           /* carriage return, = ok */
  236.             if (echo)
  237.                 putstring (scrn, "\015\012");               /* newline */
  238.             *s = '\0';                                       /* terminate the string */
  239.             return (c);                                       /* return ok */
  240.             break;
  241.         case 21:                                           /* kill line */
  242.             for (i = 0; i < s - save; i++) {               /* length of line */
  243.                 if (echo) {                                   /* erase */
  244.                     parse (&screens[scrn], (unsigned char *) &backspace, 1);
  245.                     parse (&screens[scrn], (unsigned char *) " ", 1);
  246.                     parse (&screens[scrn], (unsigned char *) &backspace, 1);
  247.                 }
  248.             }
  249.             s = save;                                       /* reset line */
  250.             break;
  251.         case 0:                                           /* do nothing */
  252.             break;
  253.         default:                                           /* not special char */
  254.             if (c > 31 && c < 127) {                       /* printable */
  255.                 if (echo)
  256.                     parse (&screens[scrn], &c, 1);           /* display */
  257.                 *s++ = c;                                   /* add to string */
  258.                 count++;                                   /* length of string */
  259.             }
  260.             else                                           /* acts as eol */
  261.                 return (c);                                   /* value of special char */
  262.  
  263.             if (count == lim) {                               /* to length limit */
  264.                 *s = '\0';                                   /* terminate */
  265.                 return (c);
  266.             }
  267.             break;
  268.         }
  269.  
  270.     }
  271. }
  272.  
  273. /************************************************************************/
  274. /* captcon capture everything from a connection into the capture list return -1 on closed
  275.    connection, else 0, 1 if paused 
  276. /*********************************************************************** */
  277.  
  278. short captcon(short cnum, short mywindow)
  279. {
  280.     short            capturesize, cnt = 0;
  281.     unsigned    char s[80];                                   /* temporary string */
  282.  
  283.     /* if (fromtty && n_scrlck()) return(TRUE);    /* if paused, nothing to do */
  284.     capturesize = screens[mywindow].capturesize;
  285.     do {
  286.         cnt = netread (cnum, &s[0], 64);                   /* get some from queue */
  287.         if ((cnt + capturesize) < captlistsize) {
  288.             BlockMove (&s[0], &captlist[capturesize], (long) cnt);
  289.             capturesize += cnt;
  290.         }
  291.  
  292.         /* demux all packets */
  293.     } while ((cnt > 0) && ((cnt + capturesize) < captlistsize));
  294.  
  295.     captlist[capturesize] = 0;
  296.     screens[mywindow].capturesize = capturesize;
  297.  
  298.     return (cnt);                                           /* 0 normally, -1 if connection closed */
  299. }
  300.  
  301. /************************************************************************/
  302. /* telnet filter telnet options on incoming data
  303. /*********************************************************************** */
  304.  
  305. short    telnet (int port, int cnt, unsigned char *s)
  306. {
  307.     register int i, mylen, myport;
  308.     char    printline[256];                                   /* line to display */
  309.  
  310.     myport = WindByPort (port);
  311.     for (i = 0; i < cnt; i++) {                               /* put on screen */
  312.         if (*(s + i) & 128) {                               /* if over ASCII 128 */
  313.             sprintf (printline, " %d ", *(s + i));           /* show as number */
  314.             mylen = strlen (printline);
  315.             parse (&screens[myport], (unsigned char *) &printline[0], mylen);
  316.         }
  317.         else
  318.             parse (&screens[myport], (s + i), 1);
  319.     }
  320.     return (TRUE);
  321. }
  322.  
  323. /************************************************************************/
  324. /*     dumpcon take everything from a connection and send it to the screen
  325.     return -1 on closed connection, else 0, 1 if paused
  326. /*********************************************************************** */
  327.  
  328. int dumpcon (int cnum, int mywindow)
  329. {                                                           /* BYU 2.4.12 */
  330.     short   i1, i2, cnt = 0, result = 0;                   /* BYU 2.4.12 */
  331.     unsigned char s1[64], s2[128];                           /* temporary strings */
  332.  
  333.     /* if (fromtty && n_scrlck()) return(TRUE);        /* if paused, nothing to do */
  334.  
  335.     do {
  336.         cnt = netread (cnum, &s1[0], 64);                   /* get some from queue */
  337.  
  338.         /* Search the incoming data for status codes and newlines */
  339.         i1 = 0;
  340.         i2 = 0;
  341.         while (i1 < cnt) {
  342.  
  343.             /* Check for 3 digit codes beginning with "5" at the beginning of each line. */
  344.             if (s1[i1] == '\012' || s1[i1] == '\015') {       /* BYU 2.4.12 */
  345.                 response_count[mywindow] = 0;               /* BYU 2.4.12 */
  346.             }
  347.             else if (response_count[mywindow] < 4) {       /* BYU 2.4.12 */
  348.                 response_data[mywindow][response_count[mywindow]++] = s1[i1];    /* BYU 2.4.12 */
  349.                 if (response_count[mywindow] == 4) {       /* BYU 2.4.12 */
  350.                     if (response_data[mywindow][0] == '5' &&    /* BYU 2.4.12 */
  351.                         response_data[mywindow][1] >= '0' &&    /* BYU 2.4.12 */
  352.                         response_data[mywindow][1] <= '9' &&    /* BYU 2.4.12 */
  353.                         response_data[mywindow][2] == '0' &&    /* BYU 2.4.12 */
  354.                         response_data[mywindow][2] <= '9' &&    /* BYU 2.4.12 */
  355.                         response_data[mywindow][3] == ' ') /* BYU 2.4.12 */
  356.                         result = -1;                       /* BYU 2.4.12 - Abort indicated by other
  357.                                                               host */
  358.                 }
  359.             }
  360.  
  361.             /* If a "newline" is found then force a "carriage return" immediately. */
  362.             if ('\012' == (s2[i2++] = s1[i1++]))
  363.                 s2[i2++] = '\015';
  364.         }
  365.  
  366.         telnet (cnum, i2, &s2[0]);                           /* display on screen, etc. */
  367.  
  368.         /* demux all packets */
  369.     } while (cnt > 0);
  370.  
  371.     return (result);                                       /* BYU 2.4.12 - 0 normally, -1 if
  372.                                                               connection closed */
  373. }
  374.  
  375. /************************************************************************/
  376. /*     getword: remove a word from a string.  Things within quotes are assumed
  377.     to be one word. return TRUE on success, FALSE on end of string
  378. /*********************************************************************** */
  379.  
  380. short getword (char *string, char *word)
  381. {
  382.     char   *p, *q;
  383.     int     i = 0;
  384.  
  385.     p = stpblkp (string);                                   /* skip leading blanks */
  386.     if (!(*p)) {                                           /* no words in string */
  387.         word[0] = '\0';
  388.         return (FALSE);
  389.     }
  390.     if (*p == '!') {                                       /* ! is a word */
  391.         word[0] = *p;
  392.         word[1] = '\0';
  393.         strcpy (string, ++p);
  394.         return (TRUE);
  395.     }
  396.     if (*p == '\"') {                                       /* word delimited by quotes */
  397.         while (p[++i] && p[i] != '\"')
  398.             word[i - 1] = p[i];
  399.         word[i - 1] = '\0';
  400.         if (!p[i])
  401.             ftpclient_debug_print ("Missing \". Assumed at end of string.");
  402.         else
  403.             i++;
  404.         q = p + i;
  405.     }
  406.     else
  407.         q = stptok (p, word, 50, " \t\015\012");           /* get word, max len 50 */
  408.     p = stpblkp (q);                                       /* remove trailing blanks */
  409.     strcpy (string, p);                                       /* remove extracted stuff */
  410.     return (TRUE);
  411. }
  412.  
  413. /************************************************************************/
  414. /* lowercase: convert a string to lowercase
  415. /*********************************************************************** */
  416.  
  417. short lowercase(char *word)
  418. {
  419.     short     i;
  420.  
  421.     for (i = 0; word[i] = tolower (word[i]); i++) ;
  422.     return (TRUE);
  423. }
  424.  
  425. /************************************************************************/
  426. /*    finduniq: find name that is a unique prefix of one of the entries in a list.
  427.     Return position of the entry, NONE if none, AMBIGUOUS if more than one.
  428. /*********************************************************************** */
  429.  
  430. int     finduniq (unsigned char *name, int listsize)
  431. {
  432.     int     i, j = NONE, len;
  433.     unsigned char *p, cmdstring[256];
  434.  
  435.     len = strlen ((char *) name);
  436.     for (i = 0; i < listsize; i++) {
  437.         GetIndString (cmdstring, FTPCOMMANDS, i + 1);
  438.         p = (unsigned char *) p2cstr (cmdstring);
  439.         if (!strncmp ((char *) name, (char *) cmdstring, len)) {    /* prefix */
  440.             if (len == strlen ((char *) cmdstring))
  441.                 return (i + 1);                               /* exact match */
  442.             if (j != NONE)
  443.                 j = AMBIGUOUS;                               /* more than one match */
  444.             else
  445.                 j = i + 1;                                   /* note prefix found */
  446.         }
  447.     }
  448.     return (j);                                               /* prefix */
  449. }
  450.  
  451. /************************************************************************/
  452. /*     checkoredir: check for output redirection.  If the command contains a >,
  453.     assume a filename follows and extract it.  Remove the redirection from
  454.     the original command. Also change \ to / return TRUE if redirection
  455.     specified, FALSE otherwise
  456. /*********************************************************************** */
  457. Boolean checkoredir(char *command, char *filename, short slashflip)
  458. {
  459.     short    i;
  460.  
  461.     filename[0] = '\0';
  462.     for (i = 0; (command[i] != '>'); i++) {                   /* process command part */
  463.         if (slashflip && command[i] == '\\')
  464.             command[i] = '/';
  465.         if (!command[i])
  466.             return (FALSE);                                   /* no redirection */
  467.     }
  468.     getword (&command[i + 1], filename);                   /* get redirected filename */
  469.     command[i] = '\0';
  470.     return (TRUE);
  471. }
  472.  
  473. /************************************************************************/
  474. /* getnname: get next name from captured list names delimited by newlines - <CR> or <LF>
  475. /*********************************************************************** */
  476. Boolean getnname(char *string, char *word)
  477. {
  478.     char   *s;
  479.  
  480.     s = string;
  481.     while ((*string == '\012') || (*string == '\015'))
  482.         string++;                                           /* skip initial newlines */
  483.     if (!(*string))
  484.         return (FALSE);                                       /* end of captlist */
  485.     while ((*string != '\012') && (*string != '\015') && (*string))
  486.         *(word++) = *(string++);
  487.     while ((*string == '\012') || (*string == '\015'))
  488.         string++;                                           /* skip trailing newline */
  489.     *word = '\0';
  490.     strcpy (s, string);
  491.     return (TRUE);
  492. }
  493.  
  494. /********************************************************************/
  495. /*     FTP PI Protocol interpreter for user interface commands Will permit any command to
  496.     be abbreviated uniquely. Recognizes commands, translates them to the protocol
  497.     commands to be sent to the other server, and uses userftpd, the daemon, to do data
  498.     transfers.
  499. /*********************************************************************** */
  500. short ftppi (char *command)
  501. {
  502.     Boolean needanswer;
  503.     int     cmdno, i, cmd_status;
  504.     char    cmdname[20], word[PATHLEN], line[MAXFTP], answer[20], ofilename[PATHLEN];
  505.     unsigned char destname[50];                               /* who to connect to */
  506.     char    printline[256];                                   /* line to display */
  507.     Str255    scratchPstring;
  508.     
  509.     if (captlist == 0) {
  510.         captlist = (unsigned char *) NewPtrClear ((long) captlistsize);
  511.         /* newfile = (unsigned char *) NewPtrClear( (long) PATHLEN);        /* Pointer, no allocation
  512.            necessary */
  513.         transfile = (unsigned char *) NewPtrClear ((long) PATHLEN);
  514.         xs = (unsigned char *) NewPtrClear ((long) (BUFFERS + 10));
  515.     }
  516.  
  517.     // Should check for not enough memory here!
  518.     
  519.     /* Indicates waiting for response *//* BYU 2.4.12 */
  520.     response_count[scrn] = 0;                               /* BYU 2.4.12 */
  521.  
  522.     /* get command number */
  523.     if (!getword (command, cmdname))
  524.         return (FALSE);                                       /* get command name */
  525.  
  526.     /* removes first word from command */
  527.     lowercase (cmdname);
  528.     cmdno = finduniq ((unsigned char *) cmdname, NCMDS);   /* search cmdlist for prefix */
  529.     if (cmdno == AMBIGUOUS) {                               /* not unique abbreviation */
  530.         putstring (scrn, "?Ambiguous command\015\012");
  531.         return (FALSE);
  532.     }
  533.     if (cmdno == NONE) {                                   /* not a prefix of any command */
  534.         putstring (scrn, "?Invalid command\015\012");
  535.         return (FALSE);
  536.     }
  537.  
  538.     /* change \ to / and check if command output redirected */
  539.     if (cmdno != BANG) {                                   /* don't alter shell escape */
  540.         if (cmdno != LLS)                                   /* do not flip slashes for LLS */
  541.             checkoredir(command, ofilename, slashflip);   /* check redirection, flip \ */
  542.         else
  543.             checkoredir(command, ofilename, FALSE);       /* check redirection */
  544.     }
  545.  
  546.     /* process commands */
  547.     switch (cmdno) {
  548.     case QMARK:
  549.     case HELP:
  550.         if (!command[0]) {                                   /* no argument */
  551.             putstring (scrn, "Commands may be abbreviated:\015\012");
  552.  
  553.             /* display command list */
  554.             printline[0] = '\0';
  555.             for (i = 2; i < NCMDS; i++) {
  556.                 GetIndString (scratchPstring, FTPCOMMANDS, i + 1);
  557.                 PtoCstr(scratchPstring);
  558.                 sprintf (word, "%-16s", (char *)scratchPstring);               /* get word from list */
  559.                 strcat (printline, word);                   /* add to line */
  560.                 if ((i - 2) % 5 == 4) {                       /* display line */
  561.                     printline[79] = '\0';
  562.                     putstring (scrn, printline);
  563.                     putstring (scrn, "\015\012");
  564.                     printline[0] = '\0';
  565.                 }
  566.             }
  567.             if (i % 5 != 4) {
  568.                 putstring (scrn, printline);               /* last line */
  569.                 putstring (scrn, "\015\012");
  570.             }
  571.             return (TRUE);
  572.         }
  573.  
  574.         /* help for specific commands */
  575.         else {
  576.             while (getword (command, word)) {               /* loop for all args */
  577.                 i = finduniq ((unsigned char *) word, NCMDS);    /* which command? */
  578.                 if (i == AMBIGUOUS)                           /* non-unique command name */
  579.                     sprintf (printline, "?Ambiguous help command %s", word);
  580.                 else if (i == NONE)                           /* no such command */
  581.                     sprintf (printline, "?Invalid help command %s", word);
  582.                 else {                                       /* display help string */
  583.                     GetIndString (scratchPstring, HELPRESID, i);
  584.                     PtoCstr(scratchPstring);
  585.                 }
  586.                 putstring (scrn, (char *)scratchPstring);
  587.                 putstring (scrn, "\015\012");
  588.             }
  589.             return (TRUE);
  590.         }
  591.         break;
  592.     case BANG:                                               /* shell escape */
  593.         return (TRUE);
  594.     case BELL:
  595.         if (getword (command, word)) {                       /* scan arg */
  596.             lowercase (word);
  597.             if (!strcmp (word, "off"))
  598.                 bell = FALSE;
  599.             else if (!strcmp (word, "on"))
  600.                 bell = TRUE;
  601.             else
  602.                 bell = !bell;
  603.         }
  604.         else
  605.             bell = !bell;
  606.         if (bell)
  607.             ftpclient_debug_print ("Bell mode on.");
  608.         else
  609.             ftpclient_debug_print ("Bell mode off.");
  610.         return (TRUE);
  611.     case BYE:
  612.     case QUIT:
  613.         cmd_status = ftpdo (scrn, "QUIT", ofilename);
  614.         netclose (screens[scrn].port);
  615.         destroyport (scrn);
  616.         return (TRUE);
  617.     case DEBUG:                                           /* turn on/off debugging, optional level */
  618.         if (TelInfo->debug) {
  619.             TelInfo->debug = 0;
  620.             ftpclient_debug_print ("Debug off");
  621.         }
  622.         else {
  623.             TelInfo->debug = 1;
  624.             ftpclient_debug_print ("Debug on");
  625.         }
  626.         return (TRUE);
  627.     case GLOB:                                               /* wildcard expansion */
  628.         if (getword (command, word)) {
  629.             lowercase (word);
  630.             if (!strcmp (word, "off"))
  631.                 glob = FALSE;
  632.             else if (!strcmp (word, "on"))
  633.                 glob = TRUE;
  634.             else
  635.                 glob = !glob;
  636.         }
  637.         else
  638.             glob = !glob;
  639.         if (glob)
  640.             ftpclient_debug_print ("Globbing on.");
  641.         else
  642.             ftpclient_debug_print ("Globbing off.");
  643.         return (TRUE);
  644.     case HASH:                                               /* hash mark printing */
  645.         if (getword (command, word)) {
  646.             lowercase (word);
  647.             if (!strcmp (word, "off"))
  648.                 hash = FALSE;
  649.             else if (!strcmp (word, "on"))
  650.                 hash = TRUE;
  651.             else
  652.                 hash = !hash;
  653.         }
  654.         else
  655.             hash = !hash;
  656.         if (hash)
  657.             ftpclient_debug_print ("Hash mark printing on (1024 bytes/hash mark).");
  658.         else
  659.             ftpclient_debug_print ("Hash printing off.");
  660.         return (TRUE);
  661.     case INTERACTIVE:                                       /* prompting on multiple transfers */
  662.         prompt = TRUE;
  663.         putstring (scrn, "Interactive mode on.\015\012");
  664.         return (TRUE);
  665.     case LCD:                                               /* change local directory */
  666.         if (*(stpblkp (command))) {                           /* BYU 2.4.17 - CD */
  667.             getword (command, word);                       /* BYU 2.4.17 */
  668.             if (ChangeDirectory(&(TelInfo->FTPClientDirID), &(TelInfo->FTPClientVRefNum), word))                               /* BYU 2.4.17 */
  669.                 putstring (scrn, "Unable to change directory\015\012");
  670.         }
  671.         PathNameFromDirID(TelInfo->FTPClientDirID, TelInfo->FTPClientVRefNum, scratchPstring);
  672.         PtoCstr(scratchPstring);
  673.         sprintf (printline, "Local directory now %s\015\012", (char *)scratchPstring);
  674.         putstring (scrn, printline);
  675.         return (TRUE);
  676.     case LDIR:                                               /* local DIR */
  677.     case LLS:
  678.         putstring (scrn, "Directory ");
  679.         if (!(*(stpblkp (command)))) {                       /* null response ok */
  680.             PathNameFromDirID(TelInfo->FTPClientDirID, TelInfo->FTPClientVRefNum, scratchPstring);
  681.             PtoCstr(scratchPstring);
  682.             putstring (scrn, (char *)scratchPstring);
  683.             sprintf (line, "*");
  684.         }
  685.         else {
  686.             putstring(scrn, command);
  687.             sprintf (line, "%s", command);
  688.         }
  689.  
  690.         putstring (scrn, "\015\012");
  691.         strcpy(Template, &line[0]);
  692.         if (NULL == (newfile = (unsigned char *) firstname (Template, TelInfo->FTPClientDirID, TelInfo->FTPClientVRefNum, &ClientDirectoryState))) {
  693.             putstring (scrn, "No files found\015\012");
  694.         }
  695.         else {
  696.             putstring (scrn, (char *) newfile);
  697.             putstring (scrn, "\015\012");
  698.             while (NULL != (newfile = (unsigned char *) nextname (Template, &ClientDirectoryState))) {
  699.                 putstring (scrn, (char *) newfile);
  700.                 putstring (scrn, "\015\012");
  701.             }
  702.         }
  703.         return (TRUE);
  704.     case NONINTERACTIVE:                                   /* turn off interactive prompting */
  705.         prompt = FALSE;
  706.         ftpclient_debug_print ("Interactive mode off.");
  707.         return (TRUE);
  708.     case OPEN:                                               /* open connection to host */
  709.         PresentOpenConnectionDialog();                        /* Open a connection */
  710.         return (TRUE);
  711.     case PROMPT:                                           /* interactive prompting */
  712.         if (getword (command, word)) {
  713.             lowercase (word);
  714.             if (!strcmp (word, "off"))
  715.                 prompt = FALSE;
  716.             else if (!strcmp (word, "on"))
  717.                 prompt = TRUE;
  718.             else
  719.                 prompt = !prompt;
  720.         }
  721.         else
  722.             prompt = !prompt;
  723.         if (prompt)
  724.             ftpclient_debug_print ("Interactive mode on.");
  725.         else
  726.             ftpclient_debug_print ("Interactive mode off.");
  727.         return (TRUE);
  728.     case SENDPORT:                                           /* send PORT commands for each transfer */
  729.         if (getword (command, word)) {
  730.             lowercase (word);
  731.             if (!strcmp (word, "off"))
  732.                 sendport = FALSE;
  733.             else if (!strcmp (word, "on"))
  734.                 sendport = TRUE;
  735.             else
  736.                 sendport = !sendport;
  737.         }
  738.         else
  739.             sendport = !sendport;
  740.         if (sendport)
  741.             ftpclient_debug_print ("Use of PORT cmds on.");
  742.         else
  743.             ftpclient_debug_print ("Use of PORT cmds off.");
  744.         return (TRUE);
  745.     case SLASHFLIP:                                       /* change \ to / */
  746.         if (getword (command, word)) {
  747.             lowercase (word);
  748.             if (!strcmp (word, "off"))
  749.                 slashflip = FALSE;
  750.             else if (!strcmp (word, "on"))
  751.                 slashflip = TRUE;
  752.             else
  753.                 slashflip = !slashflip;
  754.         }
  755.         else
  756.             slashflip = !slashflip;
  757.         if (slashflip)
  758.             ftpclient_debug_print ("Slash translation on.");
  759.         else
  760.             ftpclient_debug_print ("Slash translation off.");
  761.         return (TRUE);
  762.     case STATUS:                                           /* display status info */
  763.         sprintf (printline, "Connected to %s", destname);
  764.         ftpclient_debug_print (printline);
  765.         if (ftpfilemode == FASCII)
  766.             ftpclient_debug_print ("Transfer mode is ascii.");
  767.         else
  768.             ftpclient_debug_print ("Transfer mode is binary.");
  769.         if (bell)
  770.             ftpclient_debug_print ("Bell on.");
  771.         else
  772.             ftpclient_debug_print ("Bell off.");
  773.         if (TelInfo->debug) {
  774.             ftpclient_debug_print ("Debug on");
  775.         }
  776.         else
  777.             ftpclient_debug_print ("Debug off");
  778.         if (glob)
  779.             ftpclient_debug_print ("Filename globbing on.");
  780.         else
  781.             ftpclient_debug_print ("Filename globbing off.");
  782.         if (hash)
  783.             ftpclient_debug_print ("Hash-mark printing on.");
  784.         else
  785.             ftpclient_debug_print ("Hash-mark printing off.");
  786.         if (prompt)
  787.             ftpclient_debug_print ("Interactive prompting on.");
  788.         else
  789.             ftpclient_debug_print ("Interactive prompting off.");
  790.         if (sendport)
  791.             ftpclient_debug_print ("Sending of port commands on.");
  792.         else
  793.             ftpclient_debug_print ("Sending of PORT cmds off.");
  794.         if (slashflip)
  795.             ftpclient_debug_print ("Flipping \\ to / on.");
  796.         else
  797.             ftpclient_debug_print ("Flipping \\ to / off.");
  798.         if (verbose)
  799.             ftpclient_debug_print ("Verbose mode on.");
  800.         else
  801.             ftpclient_debug_print ("Verbose mode off.");
  802.  
  803.         ftpclient_debug_print ("\012Remote status:");
  804.         cmd_status = ftpdo (scrn, "STAT", ofilename);
  805.  
  806.         return (TRUE);
  807.     case VERBOSE:                                           /* display informative messages */
  808.         if (getword (command, word)) {
  809.             lowercase (word);
  810.             if (!strcmp (word, "off"))
  811.                 verbose = FALSE;
  812.             else if (!strcmp (word, "on"))
  813.                 verbose = TRUE;
  814.             else
  815.                 verbose = !verbose;
  816.         }
  817.         else
  818.             verbose = !verbose;
  819.         if (verbose)
  820.             ftpclient_debug_print ("Verbose mode on.");
  821.         else
  822.             ftpclient_debug_print ("Verbose mode off.");
  823.         return (TRUE);
  824.     default:                                               /* The other commands valid only if
  825.                                                               connected (we always are here) */
  826.         switch (cmdno) {
  827.         case ACCT:                                           /* get file in binary mode */
  828.             while (!(*(stpblkp (command)))) {
  829.                 putstring (scrn, "Acct: ");
  830.                 if (ftpgets (command, 100, 1) == ABORT)
  831.                     return (FALSE);
  832.             }
  833.             sprintf (line, "ACCT %s", command);
  834.             cmd_status = ftpdo (scrn, line, ofilename);       /* get file */
  835.             return (TRUE);
  836.         case ASCII:                                       /* transfer mode */
  837.             cmd_status = ftpdo (scrn, "TYPE A", ofilename);
  838.             return (TRUE);
  839.         case MACB:                                           /* transfer mode */
  840.             if (TelInfo->MacBinary) {
  841.                 TelInfo->MacBinary = 0;
  842.                 cmd_status = ftpdo (scrn, "MACB D", ofilename);
  843.             }
  844.             else {
  845.                 TelInfo->MacBinary = 1;
  846.                 cmd_status = ftpdo (scrn, "MACB E", ofilename);
  847.             }
  848.             return (TRUE);
  849.         case BGET:                                           /* get file in binary mode */
  850.             i = ftpfilemode;                               /* save current mode */
  851.             if (i == FASCII)
  852.                 cmd_status = ftpdo (scrn, "TYPE I", ofilename);
  853.             while (!(*(stpblkp (command)))) {
  854.                 putstring (scrn, "File: ");
  855.                 if (ftpgets (command, 100, 1) == ABORT)
  856.                     return (FALSE);
  857.             }
  858.             sprintf (line, "RETR %s", command);
  859.             cmd_status = ftpdo (scrn, line, ofilename);       /* get file */
  860.             if (i == FASCII)
  861.                 cmd_status = ftpdo (scrn, "TYPE A", ofilename);    /* restore mode */
  862.             return (TRUE);
  863.         case BINARY:                                       /* binary mode */
  864.             cmd_status = ftpdo (scrn, "TYPE I", ofilename);
  865.             return (TRUE);
  866.         case BPUT:                                           /* put file in binary mode */
  867.             i = ftpfilemode;
  868.             if (i == FASCII)
  869.                 cmd_status = ftpdo (scrn, "TYPE I", ofilename);
  870.             while (!(*(stpblkp (command)))) {               /* if no arg */
  871.                 putstring (scrn, "File: ");                   /* get from user */
  872.                 if (ftpgets (command, 100, 1) == ABORT)
  873.                     return (FALSE);
  874.             }
  875.             sprintf (line, "STOR %s", command);
  876.             cmd_status = ftpdo (scrn, line, ofilename);
  877.             if (i == FASCII)
  878.                 cmd_status = ftpdo (scrn, "TYPE A", ofilename);
  879.             return (TRUE);
  880.         case CD:                                           /* change remote directory */
  881.             while (!(*(stpblkp (command)))) {               /* if no arg, get from user */
  882.                 putstring (scrn, "To: ");
  883.                 if (ftpgets (command, 100, 1) == ABORT)
  884.                     return (FALSE);                           /* abort */
  885.             }
  886.             getword (command, word);
  887.             if (!strcmp (word, "..")) {                       /* special case */
  888.                 cmd_status = ftpdo (scrn, "CDUP", ofilename);
  889.                 if (cmd_status != ERROR)
  890.                     return (TRUE);                           /* if CDUP understood */
  891. #if 0
  892.                 ftpclient_debug_print ("Trying again...");
  893.                 cmd_status = ftpdo (scrn, "XCUP", ofilename);    /* try alternative */
  894.                 if (cmd_status != ERROR)
  895.                     return (TRUE);
  896.                 ftpclient_debug_print ("Trying again...");                   /* else try usual CD */
  897. #endif
  898.             }
  899.             sprintf (line, "CWD %s", word);                   /* try CWD */
  900.             cmd_status = ftpdo (scrn, line, ofilename);
  901.             if (cmd_status != ERROR)
  902.                 return (TRUE);
  903. #if 0
  904.             ftpclient_debug_print ("Trying again...");
  905.             sprintf (line, "XCWD %s", word);               /* try XCWD */
  906.             cmd_status = ftpdo (scrn, line, ofilename);
  907. #endif
  908.             return (TRUE);
  909.         case CLOSE:                                       /* drop connection */
  910.             cmd_status = ftpdo (scrn, "QUIT", ofilename);
  911.             netclose (screens[scrn].port);
  912.             destroyport (scrn);
  913.             return (TRUE);
  914.         case DEL:
  915.         case RM:
  916.             getword (command, word);
  917.             while (!word[0]) {                               /* get arg from user */
  918.                 putstring (scrn, "File: ");
  919.                 if (ftpgets (word, 100, 1) == ABORT)
  920.                     return (FALSE);                           /* abort */
  921.             }
  922.             if (prompt) {                                   /* check interactively */
  923.                 sprintf (printline, "Delete %s? ", word);
  924.                 putstring (scrn, printline);
  925.                 ftpgets (answer, 20, 1);
  926.                 if (tolower (*(stpblkp (answer))) != 'y')
  927.                     return (TRUE);
  928.             }
  929.             sprintf (line, "DELE %s", word);
  930.             cmd_status = ftpdo (scrn, line, ofilename);
  931.             return (TRUE);
  932.         case DIR:                                           /* get list of remote files */
  933.             if (ftpfilemode == FIMAGE) {
  934.                 cmd_status = ftpdo (scrn, "TYPE A", ofilename);
  935.                 if (getword (command, word)) {
  936.                     sprintf (line, "LIST %s", word);
  937.                 }
  938.                 else
  939.                     sprintf (line, "LIST");
  940.                 strcpy (screens[scrn].ftpbuf, line);
  941.                 screens[scrn].clientflags = TYPE_I_ON_CLOSE;
  942.                 screens[scrn].ftpstate = 3;                   /* Do "LIST" when "TYPE" is finished */
  943.                 screens[scrn].ftpnext = 1;
  944.             }
  945.             else {
  946.                 if (getword (command, word)) {               /* Do DIR */
  947.                     sprintf (line, "LIST %s", word);
  948.                     cmd_status = ftpdo (scrn, line, ofilename);
  949.                 }
  950.                 else
  951.                     cmd_status = ftpdo (scrn, "LIST", ofilename);
  952.             }
  953.             return (TRUE);
  954.         case GET:
  955.         case RECV:                                           /* get remote file */
  956.             while (!(*(stpblkp (command)))) {               /* if no arg */
  957.                 putstring (scrn, "File: ");
  958.                 if (ftpgets (command, 100, 1) == ABORT)
  959.                     return (FALSE);                           /* abort */
  960.             }
  961.             sprintf (line, "RETR %s", command);
  962.             cmd_status = ftpdo (scrn, line, ofilename);
  963.             return (TRUE);
  964.         case LS:                                           /* get remote file list - short */
  965.             if (ftpfilemode == FIMAGE) {
  966.                 cmd_status = ftpdo (scrn, "TYPE A", ofilename);
  967.                 if (getword (command, word)) {
  968.                     sprintf (line, "NLST %s", word);
  969.                 }
  970.                 else
  971.                     sprintf (line, "NLST");
  972.                 strcpy (screens[scrn].ftpbuf, line);
  973.                 screens[scrn].clientflags = TYPE_I_ON_CLOSE;
  974.                 screens[scrn].ftpstate = 3;                   /* Do "NLST" when "TYPE" is finished */
  975.                 screens[scrn].ftpnext = 1;
  976.             }
  977.             else {
  978.                 if (getword (command, word)) {
  979.                     sprintf (line, "NLST %s", word);
  980.                     cmd_status = ftpdo (scrn, line, ofilename);
  981.                 }
  982.                 else
  983.                     cmd_status = ftpdo (scrn, "NLST", ofilename);
  984.             }
  985.             return (TRUE);
  986.         case MDELETE:
  987.             while (!(*(stpblkp (command)))) {               /* no arg */
  988.                 putstring (scrn, "Files: ");
  989.                 if (ftpgets (command, 100, 1) == ABORT)
  990.                     return (FALSE);                           /* abort */
  991.             }
  992.             while (getword (command, word)) {               /* for each arg */
  993.                 if (glob) {                                   /* wildcard expansion */
  994.                     sprintf (line, "NLST %s", word);
  995.                     screens[scrn].clientflags |= CAPTURE_DATA;
  996.                     cmd_status = ftpdo (scrn, line, ofilename);    /* put exapnsion in captlist */
  997.                 }
  998.                 else
  999.                     strcpy ((char *) captlist, word);       /* captlist has name(s) now */
  1000.                 while (getnname ((char *) captlist, word)) {    /* for each name */
  1001.                     if (prompt) {                           /* check */
  1002.                         sprintf (printline, "mdelete %s? ", word);
  1003.                         putstring (scrn, printline);
  1004.                         if (ftpgets (answer, 20, 1) == ABORT) {    /* abort */
  1005.                             command[0] = '\0';               /* no more processing */
  1006.                             break;                           /* quit immediately */
  1007.                         }
  1008.                         if (tolower (*(stpblkp (answer))) != 'y')
  1009.                             continue;
  1010.                     }
  1011.                     sprintf (line, "DELE %s", word);       /* delete */
  1012.                     cmd_status = ftpdo (scrn, line, ofilename);
  1013.                 }
  1014.             }
  1015.             return (TRUE);
  1016.         case MDIR:                                           /* remote multiple DIR */
  1017.             i = ftpfilemode;                               /* save mode */
  1018.             if (i == FIMAGE)
  1019.                 cmd_status = ftpdo (scrn, "TYPE A", ofilename);
  1020.             while (!(*(stpblkp (command)))) {               /* no arg */
  1021.                 putstring (scrn, "Directories: ");
  1022.                 if (ftpgets (command, 100, 1) == ABORT)
  1023.                     return (FALSE);                           /* abort */
  1024.             }
  1025.             while (getword (command, word)) {               /* for each arg */
  1026.                 if (glob) {                                   /* expand wildcards */
  1027.                     sprintf (line, "NLST %s", word);
  1028.                     screens[scrn].clientflags |= CAPTURE_DATA;
  1029.                     cmd_status = ftpdo (scrn, line, ofilename);
  1030.                 }
  1031.                 else
  1032.                     strcpy ((char *) captlist, word);
  1033.                 while (getnname ((char *) captlist, word)) {    /* for each name */
  1034.                     if (prompt) {                           /* check */
  1035.                         sprintf (printline, "mdir %s? ", word);
  1036.                         putstring (scrn, printline);
  1037.                         if (ftpgets (answer, 20, 1) == ABORT) {    /* abort */
  1038.                             command[0] = '\0';               /* no more processing */
  1039.                             break;                           /* quit immediately */
  1040.                         }
  1041.                         if (tolower (*(stpblkp (answer))) != 'y')
  1042.                             continue;
  1043.                     }
  1044.                     sprintf (line, "LIST %s", word);       /* DIR */
  1045.                     cmd_status = ftpdo (scrn, line, ofilename);
  1046.                 }
  1047.             }
  1048.             if (i == FIMAGE)
  1049.                 cmd_status = ftpdo (scrn, "TYPE I", ofilename);
  1050.             return (TRUE);
  1051.         case MGET:                                           /* get multiple files */
  1052.             getword (command, line);
  1053.             while (!line[0]) {                               /* no arg */
  1054.                 putstring (scrn, "Files: ");
  1055.                 if (ftpgets (line, 100, 1) == ABORT)
  1056.                     return (FALSE);                           /* abort */
  1057.             }
  1058.             if (getword (line, word)) {
  1059.                 sprintf (command, "NLST %s", word);
  1060.                 screens[scrn].clientflags |= CAPTURE_DATA;
  1061.                 cmd_status = ftpdo (scrn, command, ofilename);
  1062.  
  1063.                 screens[scrn].clientflags |= MGET_STATE;
  1064.             }
  1065.             return (TRUE);
  1066.         case MKDIR:                                       /* create directory */
  1067.             while (!(*(stpblkp (command)))) {               /* no arg */
  1068.                 putstring (scrn, "Directory: ");
  1069.                 if (ftpgets (command, 100, 1) == ABORT)
  1070.                     return (FALSE);                           /* abort */
  1071.             }
  1072.             sprintf (line, "XMKD %s", command);               /* try XMKD */
  1073.             cmd_status = ftpdo (scrn, line, ofilename);
  1074.             if (cmd_status != ERROR)
  1075.                 return (TRUE);
  1076.             ftpclient_debug_print ("Trying again...");
  1077.             sprintf (line, "MKD %s", command);               /* else try MKD */
  1078.             cmd_status = ftpdo (scrn, line, ofilename);
  1079.             return (TRUE);
  1080.         case MLS:
  1081.             i = ftpfilemode;
  1082.             if (i == FIMAGE)
  1083.                 cmd_status = ftpdo (scrn, "TYPE A", ofilename);
  1084.             while (!(*(stpblkp (command)))) {               /* no arg */
  1085.                 putstring (scrn, "Directories: ");
  1086.                 if (ftpgets (command, 100, 1) == ABORT)
  1087.                     return (FALSE);                           /* abort */
  1088.             }
  1089.             while (getword (command, word)) {               /* for each arg */
  1090.                 if (glob) {                                   /* exapnd wildcards */
  1091.                     sprintf (line, "NLST %s", word);
  1092.                     screens[scrn].clientflags |= CAPTURE_DATA;
  1093.                     cmd_status = ftpdo (scrn, line, ofilename);
  1094.                 }
  1095.                 else
  1096.                     strcpy ((char *) captlist, word);
  1097.                 while (getnname ((char *) captlist, word)) {    /* for each name */
  1098.                     if (prompt) {                           /* check */
  1099.                         sprintf (printline, "mls %s? ", word);
  1100.                         putstring (scrn, printline);
  1101.                         if (ftpgets (answer, 20, 1) == ABORT) {    /* abort */
  1102.                             command[0] = '\0';               /* no more processing */
  1103.                             break;                           /* quit immediately */
  1104.                         }
  1105.                         if (tolower (*(stpblkp (answer))) != 'y')
  1106.                             continue;
  1107.                     }
  1108.                     sprintf (line, "NLST %s", word);       /* DIR */
  1109.                     cmd_status = ftpdo (scrn, line, ofilename);
  1110.                 }
  1111.             }
  1112.             if (i == FIMAGE)
  1113.                 cmd_status = ftpdo (scrn, "TYPE I", ofilename);
  1114.             return (TRUE);
  1115.         case MODE:                                           /* set stream mode */
  1116.             getword (command, word);
  1117.             lowercase (word);
  1118.             if (strncmp (word, "stream", strlen (word)))
  1119.                 ftpclient_debug_print ("We only support stream mode, sorry.");
  1120.             else
  1121.                 ftpclient_debug_print ("Mode is stream.");
  1122.             return (TRUE);
  1123.         case MPUT:                                           /* put multiple files */
  1124.             getword (command, (char *) captlist);
  1125.             while (!captlist[0]) {                           /* no arg */
  1126.                 putstring (scrn, "Files: ");
  1127.                 if (ftpgets ((char *) captlist, 100, 1) == ABORT)
  1128.                     return (FALSE);                           /* abort */
  1129.             }
  1130.             if (getword ((char *) captlist, (char *) transfile)) {    /* for each arg */
  1131.                 newfile = NULL;
  1132.                 needanswer = TRUE;
  1133.                 while (needanswer) {
  1134.                     needanswer = FALSE;
  1135.                     if (glob) {                               /* local wildcard expansion */
  1136.                         if (newfile == NULL) {               /* if no expansions yet */
  1137.                             strcpy(Template, (char *)transfile);
  1138.                             newfile = (unsigned char *) firstname (Template, TelInfo->FTPClientDirID, TelInfo->FTPClientVRefNum, &ClientDirectoryState);    /* get first name */
  1139.                             if (newfile == NULL) {           /* if no expansions */
  1140.                                 sprintf (printline, "No match for %s", transfile);
  1141.                                 ftpclient_debug_print (printline);
  1142.                                 if (getword ((char *) captlist, (char *) transfile)) {
  1143.                                     needanswer = TRUE;
  1144.                                 }
  1145.                             }
  1146.                         }
  1147.                         else {                               /* not first name */
  1148.                             newfile = (unsigned char *) nextname (Template, &ClientDirectoryState);    /* get next name */
  1149.                             if (newfile == NULL) {           /* if no names, next arg */
  1150.                                 if (getword ((char *) captlist, (char *) transfile)) {
  1151.                                     needanswer = TRUE;
  1152.                                 }
  1153.                             }
  1154.                         }
  1155.                     }
  1156.                     else
  1157.                         newfile = transfile;               /* no expansion */
  1158.                     if (newfile != NULL) {
  1159. #if 1                                                       /* When prompting is fixed switch to the
  1160.                                                               code below */
  1161.                         sprintf (command, "STOR \"%s\"", newfile);    /* name may have spl chars */
  1162.                         cmd_status = ftpdo (scrn, command, ofilename);
  1163.                         screens[scrn].clientflags |= MPUT_STATE;
  1164. #else
  1165.                         if (prompt) {                       /* check */
  1166.                             sprintf (printline, "mput %s? ", newfile);
  1167.                             putstring (scrn, printline);
  1168.                             if (ftpgets (answer, 20, 1) == ABORT) {    /* abort */
  1169.                                 command[0] = '\0';           /* no more processing */
  1170.                                 break;
  1171.                             }
  1172.                             else if (tolower (*(stpblkp (answer))) == 'y') {
  1173.                                 sprintf (command, "STOR \"%s\"", newfile);    /* name may have spl
  1174.                                                                                chars */
  1175.                                 cmd_status = ftpdo (scrn, command, ofilename);
  1176.                                 screens[scrn].clientflags |= MPUT_STATE;
  1177.                             }
  1178.                         }
  1179.                         else {
  1180.                             sprintf (command, "STOR \"%s\"", newfile);    /* name may have spl chars */
  1181.                             cmd_status = ftpdo (scrn, command, ofilename);
  1182.                             screens[scrn].clientflags |= MPUT_STATE;
  1183.                         }
  1184. #endif
  1185.                     }
  1186.                 }
  1187.             }
  1188.             return (TRUE);
  1189.         case PUT:
  1190.         case SEND:                                           /* put file */
  1191.             while (!(*(stpblkp (command)))) {               /* no args */
  1192.                 putstring (scrn, "File: ");
  1193.                 if (ftpgets (command, 100, 1) == ABORT)
  1194.                     return (FALSE);
  1195.             }
  1196.             sprintf (line, "STOR %s", command);               /* put file */
  1197.             cmd_status = ftpdo (scrn, line, ofilename);
  1198.             return (TRUE);
  1199.         case PWD:
  1200. #if 0
  1201.             cmd_status = ftpdo (scrn, "XPWD", ofilename);  /* try XPWD */
  1202.             if (i != ERROR)
  1203.                 return (TRUE);
  1204.             ftpclient_debug_print ("Trying again...");
  1205. #endif
  1206.             cmd_status = ftpdo (scrn, "PWD", ofilename);   /* else try PWD */
  1207.             return (TRUE);
  1208.         case QUOTE:
  1209.             while (!(*(stpblkp (command)))) {               /* no arg */
  1210.                 putstring (scrn, "Command: ");
  1211.                 if (ftpgets (command, 100, 1) == ABORT)
  1212.                     return (FALSE);
  1213.             }
  1214.             cmd_status = ftpdo (scrn, command, ofilename); /* send command */
  1215.             return (TRUE);
  1216.         case REMOTEHELP:                                   /* get help */
  1217.             if (*(stpblkp (command))) {                       /* for specific command */
  1218.                 sprintf (line, "HELP %s", command);
  1219.                 cmd_status = ftpdo (scrn, line, ofilename);
  1220.             }
  1221.             else
  1222.                 cmd_status = ftpdo (scrn, "HELP", ofilename);    /* generic help */
  1223.             return (TRUE);
  1224.         case RENAME:                                       /* rename remote file */
  1225.             while (!(*(stpblkp (command)))) {               /* no arg */
  1226.                 putstring (scrn, "From: ");
  1227.                 if (ftpgets (command, 100, 1) == ABORT)
  1228.                     return (FALSE);
  1229.             }
  1230.             getword (command, word);
  1231.             sprintf (line, "RNFR %s", word);
  1232.             cmd_status = ftpdo (scrn, line, ofilename);       /* send rename from name */
  1233.             while (!(*(stpblkp (command)))) {               /* no second arg */
  1234.                 putstring (scrn, "To: ");
  1235.                 if (ftpgets (command, 100, 1) == ABORT) {
  1236.                     cmd_status = ftpdo (scrn, "ABOR", ofilename);
  1237.                     return (FALSE);
  1238.                 }
  1239.             }
  1240.             sprintf (line, "RNTO %s", command);               /* send rename to name */
  1241.             cmd_status = ftpdo (scrn, line, ofilename);
  1242.             return (TRUE);
  1243.         case RMDIR:                                       /* remove remote dir */
  1244.             while (!(*(stpblkp (command)))) {               /* no arg */
  1245.                 putstring (scrn, "Directory: ");
  1246.                 if (ftpgets (command, 100, 1) == ABORT)
  1247.                     return (FALSE);
  1248.             }
  1249.             sprintf (line, "XRMD %s", command);               /* try XRMD */
  1250.             cmd_status = ftpdo (scrn, line, ofilename);
  1251.             if (cmd_status != ERROR)
  1252.                 return (TRUE);
  1253.             ftpclient_debug_print ("Trying again...");
  1254.             sprintf (line, "RMD %s", command);               /* try RMD */
  1255.             cmd_status = ftpdo (scrn, line, ofilename);
  1256.             return (TRUE);
  1257.         case STRUCT:                                       /* set structure type - only file */
  1258.             getword (command, word);
  1259.             lowercase (word);
  1260.             if (strncmp (word, "file", strlen (word)))
  1261.                 ftpclient_debug_print ("We only support file structure, sorry.");
  1262.             else
  1263.                 ftpclient_debug_print ("Structure is file.");
  1264.             return (TRUE);
  1265.         case TYPE:                                           /* set transfer type */
  1266.             if (!getword (command, word)) {                   /* no arg, just show */
  1267.                 if (ftpfilemode == FASCII)
  1268.                     ftpclient_debug_print ("Transfer type is ascii.");
  1269.                 else
  1270.                     ftpclient_debug_print ("Transfer type is binary.");
  1271.             }
  1272.             lowercase (word);
  1273.             if (!strncmp (word, "ascii", strlen (word)))
  1274.                 cmd_status = ftpdo (scrn, "TYPE A", ofilename);
  1275.             else if (!strncmp (word, "binary", strlen (word)) ||
  1276.                      !strncmp (word, "image", strlen (word)))
  1277.                 cmd_status = ftpdo (scrn, "TYPE I", ofilename);
  1278.             else {
  1279.                 sprintf (printline, "Unrecognized type: %s", word);
  1280.                 ftpclient_debug_print (printline);
  1281.             }
  1282.             return (TRUE);
  1283.         case USER:                                           /* login to remote machine */
  1284.             if (!(*(stpblkp (command)))) {                   /* null response to prompt ok */
  1285.                 putstring (scrn, "Username: ");
  1286.                 if (ftpgets (command, 100, 1) == ABORT)
  1287.                     return (FALSE);
  1288.             }
  1289.             sprintf (line, "USER %s", command);               /* username */
  1290.             if ((cmd_status = ftpdo (scrn, line, ofilename)) == TRUE)
  1291.                 return (TRUE);
  1292. #if 0
  1293.             putstring (scrn, "Password: ");
  1294. #endif
  1295.             if (ftpgets (word, PATHLEN, 0) == ABORT)
  1296.                 return (FALSE);                               /* no echoing */
  1297.             sprintf (line, "PASS %s", word);               /* password */
  1298.             if ((cmd_status = ftpdo (scrn, line, ofilename)) == INCOMPLETE) {    /* if account needed */
  1299.                 do {
  1300.                     putstring (scrn, "Account: ");
  1301.                     if (ftpgets (command, 100, 1) == ABORT)
  1302.                         return (FALSE);
  1303.                 } while (!(*(stpblkp (command))));
  1304.                 sprintf (line, "ACCT %s", command);
  1305.                 cmd_status = ftpdo (scrn, line, ofilename);
  1306.             }
  1307.             return (TRUE);
  1308.         default:                                           /* unknown command */
  1309.             putstring (scrn, "?Invalid command\015\012");
  1310. #if 0
  1311.             sprintf (printline, "***Unknown command no: %d", cmdno);
  1312.             ftpclient_debug_print (printline);
  1313. #endif
  1314.             break;
  1315.         }
  1316.     }
  1317.  
  1318. }
  1319.  
  1320. /************************************************************************/
  1321. /*     ftpport return a new port number so that we don't try to re-use ports before the
  1322.     mandatory TCP timeout period.  (lifetime of a packet) use a time-based initial port
  1323.     selection scheme.
  1324. /*********************************************************************** */
  1325.  
  1326. short ftpport(int ftpscrn)
  1327. {
  1328.     unsigned int i;
  1329.     unsigned char hostnum[5];
  1330.     char    sendline[60];                            /* for port command */
  1331.  
  1332.     if (!sendport)                                    /* default port */
  1333.         return (HFTP - 1);
  1334.         
  1335.     if (curftpprt < 40000) {                        /* restart cycle */
  1336.         i = (unsigned int) TickCount ();
  1337.         curftpprt = 40000 + (i & 0x3fff);
  1338.     }
  1339.  
  1340.     i = curftpprt--;                                /* get port, update for next time */
  1341.  
  1342.     netgetip (hostnum);                                /* get my ip number */
  1343.  
  1344.     ftpdata = netlisten (i);
  1345.     screens[ftpscrn].ftpport = ftpdata;
  1346.     SetPortType(ftpdata, UDATA);
  1347.  
  1348.     sprintf (sendline, "PORT %d,%d,%d,%d,%d,%d\015\012", hostnum[0], hostnum[1], hostnum[2],
  1349.              hostnum[3], i / 256, i & 255);                   /* full port number */
  1350.  
  1351.     netpush (screens[ftpscrn].port);                /* empty command connection */
  1352.     netwrite (screens[ftpscrn].port, sendline, strlen (sendline));    /* send PORT command */
  1353.  
  1354.     return (i);                                        /* port number */
  1355. }
  1356.  
  1357. /************************************************************************/
  1358. /*     ftpdo Do whatever command is sent from the user interface using userftpd,
  1359.     the background file handler
  1360. /*********************************************************************** */
  1361. int     ftpdo (int ftpscrn, char *s, char *ofile)
  1362. {
  1363.     int     i;
  1364.     char    name[MAXFTP], name2[MAXFTP];
  1365.     char    commandbuf[MAXFTP];
  1366.     HFileParam iop;
  1367.  
  1368.     strcpy (commandbuf, s);
  1369.     for (i = 0; i < 4; i++) {
  1370.         commandbuf[i] = toupper (commandbuf[i]);           /* command to upper case */
  1371.     }
  1372.  
  1373.     if (!strncmp (commandbuf, "STOR", 4)) {                   /* put file */
  1374.         getword (&commandbuf[5], name);                       /* first arg - local file */
  1375.         if (!commandbuf[5])
  1376.             strcpy (&commandbuf[5], name);                   /* if only one argument */
  1377.         else {
  1378.             getword (&commandbuf[5], name2);               /* second arg - removes quotes etc. */
  1379.             strcpy (&commandbuf[5], name2);                   /* copy back into command */
  1380.         }
  1381.  
  1382.         ftp_mbfp = MBopen (&name[0], TelInfo->FTPClientVRefNum, TelInfo->FTPClientDirID, 
  1383.                 MB_READ +     /* BYU 2.4.18 */
  1384.                 ( ((!TelInfo->MacBinary) || (ftpfilemode == FAMODE)) ? MB_DISABLE : 0) +
  1385.                 ((ftpfilemode == FAMODE) ? MB_ISASCII : 0)
  1386.                 );
  1387.         if (ftp_mbfp == 0L) {
  1388.             putstring (ftpscrn, "Could not open file\015\012");
  1389.             return (-1);
  1390.         }
  1391.         ftpfh = 12;
  1392.  
  1393.         c2pstr (&name[0]);
  1394.         GetFileInfo (TelInfo->FTPClientVRefNum, TelInfo->FTPClientDirID, (StringPtr)&name[0], &iop);
  1395.         filelen = iop.ioFlLgLen;
  1396.         if (TelInfo->MacBinary && (ftpfilemode == FIMODE))
  1397.             filelen += iop.ioFlRLgLen;
  1398.  
  1399.         ftpport (ftpscrn);                                   /* open data connection */
  1400.         screens[ftpscrn].ftpstate = 2;
  1401.         screens[ftpscrn].ftpnext = 20;
  1402.         strcpy (screens[ftpscrn].ftpbuf, commandbuf);
  1403.         strcat (screens[ftpscrn].ftpbuf, "\015\012");
  1404.         return (1);
  1405.  
  1406.     }
  1407.     else if (!strncmp (commandbuf, "RETR", 4)) {           /* get file */
  1408.         getword (&commandbuf[5], name);                       /* remote file */
  1409.         if (commandbuf[5]) {                               /* two args present */
  1410.             getword (&commandbuf[5], name2);               /* local file */
  1411.  
  1412.             if ((ftp_mbfp = MBopen (&name2[0], TelInfo->FTPClientVRefNum, TelInfo->FTPClientDirID, MB_WRITE +    /* BYU 2.4.18 */
  1413.                               (((!TelInfo->MacBinary) || (ftpfilemode == FAMODE)) ? MB_DISABLE : 0) +
  1414.                               ((ftpfilemode == FAMODE) ? MB_ISASCII : 0)
  1415.                         )) == 0L) {
  1416.                 putstring (ftpscrn, "Cannot open file to receive\015\012");
  1417.                 return (-1);
  1418.             }
  1419.             else
  1420.                 ftpfh = 12;
  1421.         }
  1422.         else {
  1423.             if ((ftp_mbfp = MBopen (&name[0], TelInfo->FTPClientVRefNum, TelInfo->FTPClientDirID, MB_WRITE +    /* BYU 2.4.18 */
  1424.                               (((!TelInfo->MacBinary) || (ftpfilemode == FAMODE)) ? MB_DISABLE : 0)
  1425.                               + ((ftpfilemode == FAMODE) ? MB_ISASCII : 0)
  1426.                     )) == 0L) {
  1427.                 putstring (ftpscrn, "Cannot open file to receive\015\012");
  1428.                 return (-1);
  1429.             }
  1430.             else
  1431.                 ftpfh = 12;
  1432.         }
  1433.  
  1434.         strcpy (&commandbuf[5], name);                       /* Put remote name back into command */
  1435.  
  1436.         ftpport (ftpscrn);                                   /* open data connection */
  1437.         screens[ftpscrn].ftpstate = 2;
  1438.         screens[ftpscrn].ftpnext = 30;
  1439.         strcpy (screens[ftpscrn].ftpbuf, commandbuf);
  1440.         strcat (screens[ftpscrn].ftpbuf, "\015\012");
  1441.         return (1);
  1442.     }
  1443.     else if (!strncmp (commandbuf, "LIST", 4) || !strncmp (commandbuf, "NLST", 4)) {
  1444.  
  1445.         if ((screens[ftpscrn].clientflags & CAPTURE_DATA) != 0)
  1446.             screens[ftpscrn].capturesize = 0;               /* Size of captured data */
  1447.  
  1448.         ftpport (ftpscrn);                                   /* data connection */
  1449.         screens[ftpscrn].ftpstate = 2;
  1450.         screens[ftpscrn].ftpnext = 40;
  1451.         strcpy (screens[ftpscrn].ftpbuf, commandbuf);
  1452.         strcat (screens[ftpscrn].ftpbuf, "\015\012");
  1453.         return (1);
  1454.  
  1455.     }
  1456.     else if (!strncmp (commandbuf, "TYPE", 4)) {
  1457.         if (toupper (commandbuf[5]) == 'I')
  1458.             ftpfilemode = FIMAGE;                           /* Remember mode */
  1459.         else if (toupper (commandbuf[5]) == 'A')
  1460.             ftpfilemode = FASCII;
  1461.  
  1462.     }
  1463.  
  1464.     netpush (screens[ftpscrn].port);
  1465.  
  1466.     strcat (commandbuf, "\015\012");                       /* BYU 2.4.11 */
  1467.     netwrite (screens[ftpscrn].port, commandbuf, strlen (commandbuf));    /* BYU 2.4.11 - send
  1468.                                                                            command */
  1469.     c2pstr(ofile);
  1470.     
  1471.     if (((screens[ftpscrn].clientflags & CAPTURE_DATA) == 0) && ofile[0]) {    /* command redirected */
  1472.         if ((screens[ftpscrn].ftpstate != 20) && (screens[ftpscrn].ftpstate != 30)) {    /* not get or put */
  1473.             if (0 > (ftpfh = ftpopen ((StringPtr)ofile)))
  1474.                 ftpclient_debug_print (" Cannot open output file.");
  1475.             else if (ftpdata > -1) {
  1476.                 screens[ftpscrn].ftpstate = 30;               /* act as get, since data goes into file */
  1477.             }
  1478.             else {
  1479.                 /* Close(ftpfh);        /* BYU LSC */
  1480.                 ftpfh = 0;
  1481.             }
  1482.         }
  1483.     }
  1484.  
  1485.     return (FALSE);
  1486. }
  1487.  
  1488. /************************************************************************/
  1489. /* userftpd FTP receive and send file functions
  1490. /*********************************************************************** */
  1491.  
  1492. short userftpd (int code, int myport)
  1493. {
  1494.     Boolean needanswer;
  1495.     long    mytime;
  1496.     int     cmd_status, connection_status, ftpstate, i, mycode, myftpdata, mytelport, mywindow;
  1497.     char    command[MAXFTP], printline[MAXFTP], word[MAXFTP];
  1498.  
  1499.     mycode = code;
  1500.     connection_status = 0;                                   /* BYU 2.4.12 - assume good connection
  1501.                                                               status */
  1502.     ftpstate = 1;
  1503.  
  1504.     mywindow = WindByPort (myport);
  1505.     if (mywindow >= 0) {
  1506.         if (myport == screens[mywindow].port) {
  1507.             ftpstate = screens[mywindow].ftpstate;
  1508.             myftpdata = -1;
  1509.         }
  1510.         else {
  1511.             ftpstate = screens[mywindow].ftpstate;
  1512.             myftpdata = screens[mywindow].ftpport;
  1513.         }
  1514.     }
  1515.  
  1516.     if (mywindow < 0)
  1517.         return (0);
  1518.  
  1519.     mytelport = screens[mywindow].port;
  1520.  
  1521.     switch (ftpstate) {
  1522.     default:                                               /* unknown */
  1523.         break;
  1524.  
  1525.     case 1:
  1526.         if ((mycode == CONDATA) && (myport == mytelport))
  1527.             connection_status = dumpcon (myport, mywindow);
  1528.         break;
  1529.  
  1530.         /* Wait for response from "PORT" command, then send ftp command */
  1531.     case 2:
  1532.         if (mycode == CONDATA) {
  1533.             connection_status = dumpcon (myport, mywindow);
  1534.             netpush (screens[mywindow].port);
  1535.             netwrite (screens[mywindow].port, screens[mywindow].ftpbuf, strlen (screens[mywindow].ftpbuf));    /* send command */
  1536.             screens[mywindow].ftpstate = screens[mywindow].ftpnext;
  1537.         }
  1538.         break;
  1539.  
  1540.         /* Wait for response from "TYPE" command, then send ftp command */
  1541.     case 3:
  1542.         if (mycode == CONDATA) {
  1543.             connection_status = dumpcon (myport, mywindow);
  1544.             cmd_status = ftpdo (mywindow, screens[mywindow].ftpbuf, "");
  1545.         }
  1546.         break;
  1547.  
  1548.     case 5:
  1549.         /* Get the next file of an MGET. */
  1550.         if ((screens[mywindow].clientflags & CAPTURE_DATA) != 0) {
  1551.             screens[mywindow].clientflags &= ~CAPTURE_DATA;
  1552.         }
  1553.  
  1554.         /* After capturing the data, initiate the file transfer(s) */
  1555.         if ((screens[mywindow].clientflags & MGET_STATE) != 0) {
  1556.             if (screens[mywindow].capturesize > 0) {
  1557.                 screens[mywindow].ftpstate = 6;
  1558.                 netputuev (CONCLASS, CONDATA, mytelport,0);  /* Stay alive to transfer file */
  1559.             }
  1560.             else {
  1561.                 screens[mywindow].clientflags &= ~MGET_STATE;
  1562.                 screens[mywindow].ftpstate = 1;
  1563.             }
  1564.         }
  1565.         break;
  1566.  
  1567.         /* Receive one MGET file. */
  1568.     case 6:
  1569.         connection_status = dumpcon (myport, mywindow);
  1570.         if (getnname ((char *) captlist, (char *) word)) { /* for each name */
  1571. #if 0
  1572.             if (prompt) {                                   /* check */
  1573.                 sprintf (printline, "mget %s? ", word);
  1574.                 putstring (mywindow, printline);
  1575.                 if (ftpgets (answer, 20, 1) == ABORT) {       /* abort */
  1576.                     command[0] = '\0';                       /* no more processing */
  1577.                     break;                                   /* quit immediately */
  1578.                 }
  1579.                 if (tolower (*(stpblkp (answer))) != 'y')
  1580.                     continue;
  1581.             }
  1582.             else {
  1583. #endif
  1584.                 sprintf (printline, "Receiving %s\015\013", word);
  1585.                 putstring (mywindow, printline);
  1586. #if 0
  1587.             }
  1588. #endif
  1589.             sprintf (command, "RETR \"%s\"", word);
  1590.             if ((cmd_status = ftpdo (mywindow, command, "")) < 0) {
  1591.                 screens[mywindow].clientflags &= ~MGET_STATE;
  1592.                 screens[mywindow].ftpstate = 1;
  1593.             }
  1594.         }
  1595.         else {
  1596.             screens[mywindow].clientflags &= ~MGET_STATE;
  1597.             screens[mywindow].ftpstate = 1;
  1598.         }
  1599.         break;
  1600.  
  1601.         /* Send a file to the remote connection */
  1602.     case 20:
  1603.  
  1604.         if (mycode == CONFAIL)
  1605.             mycode = CONCLOSE;                               /* something went wrong */
  1606.  
  1607.         if (mycode == CONOPEN) {
  1608.             screens[mywindow].ftpstate = 21;
  1609.             transtime = TickCount ();
  1610.             translen = 0;
  1611.             towrite = 0;
  1612.             xp = 0;
  1613.             netputuev (CONCLASS, CONDATA, myport,0);
  1614.         }
  1615.         else if ((mycode == CONDATA) && (myport == mytelport)) {
  1616.             connection_status = dumpcon (myport, mywindow);
  1617.         }
  1618.         break;
  1619.  
  1620.     case 21:
  1621.         /* transfer file(s) to the other host via ftp request file is already open = ftpfh */
  1622.         if (mycode == CONDATA) {
  1623.             if (myport == mytelport) {
  1624.                 connection_status = dumpcon (myport, mywindow);
  1625.             }
  1626.             else if (myport == myftpdata) {
  1627.  
  1628.                 netputuev (CONCLASS, CONDATA, myport,0);       /* Stay alive */
  1629.  
  1630.                 if (towrite <= xp) {
  1631.  
  1632.                     i = BUFFERS;
  1633.                     towrite = MBread (ftp_mbfp, xs, i);
  1634.                     xp = 0;
  1635.                 }
  1636.  
  1637.                 if ((towrite <= 0) || netest (myftpdata)) {/* we are done */
  1638.                     if (ftp_mbfp->fd != 0)
  1639.                         MBclose (ftp_mbfp);                   /* BYU - close input file */
  1640.                     screens[mywindow].ftpstate = 22;
  1641.                     break;
  1642.                 }
  1643.  
  1644.                 if (ftpfilemode == FAMODE)
  1645.                     i = Sfwrite (myftpdata, &xs[xp], (int) towrite - xp);
  1646.                 else
  1647.                     i = netwrite (myftpdata, &xs[xp], (int) towrite - xp);
  1648.  
  1649.                 if (i > 0) {
  1650.                     xp += i;
  1651.                     translen += i;
  1652.                 }
  1653.  
  1654.                 mytime = TickCount ();
  1655.                 if ((transtime + 800) < mytime) {
  1656.                     transtime = mytime;
  1657.                     sprintf (printline, "%ld/%ld bytes sent.\015\013", translen, filelen);
  1658.                     i = strlen (printline);
  1659.                     parse (&screens[mywindow], (unsigned char *) &printline[0], i);
  1660.                 }
  1661.             }
  1662.         }
  1663.  
  1664.         break;
  1665.  
  1666.     case 22:                                               /* wait for data to be accepted */
  1667.         netputuev (CONCLASS, CONDATA, myport,0);               /* Stay alive */
  1668.  
  1669.         fcnt = netpush (myftpdata);                           /* will go negative on err */
  1670.         if (!fcnt || netest (myftpdata)) {
  1671.             mycode = CONCLOSE;
  1672.             sprintf (printline, "%ld/%ld bytes sent.\015\013", translen, filelen);
  1673.             parse (&screens[mywindow], (unsigned char *) &printline[0], strlen (printline));
  1674.         }
  1675.         if ((mycode == CONDATA) && (myport == mytelport))
  1676.             connection_status = dumpcon (myport, mywindow);
  1677.         break;
  1678.  
  1679.         /* Get a file from the remote connection */
  1680.     case 30:
  1681.         if (mycode == CONFAIL)
  1682.             mycode = CONCLOSE;                               /* something went wrong */
  1683.  
  1684.         if (mycode == CONOPEN) {
  1685.             screens[mywindow].ftpstate = 31;
  1686.             filelen = xp = 0;
  1687.             transtime = TickCount ();
  1688.             translen = 0L;
  1689.         }
  1690.         else if ((mycode == CONDATA) && (myport == mytelport)) {
  1691.             connection_status = dumpcon (myport, mywindow);
  1692.         }
  1693.         break;
  1694.  
  1695.         /* file has already been opened, take everything from the connection and place into the
  1696.            open file: ftpfh */
  1697.     case 31:
  1698.         if (mycode == CONDATA) {
  1699.             if (myport == mytelport) {
  1700.                 connection_status = dumpcon (myport, mywindow);
  1701.             }
  1702.             else if (myport == myftpdata) {
  1703.  
  1704.                 /* wait until xs is full before writing to disk */
  1705.                 if (filelen <= 2000) {
  1706.  
  1707.                     if (xp) {
  1708.                         if (0 > MBwrite (ftp_mbfp, xs, xp))
  1709.                             mycode = CONCLOSE;
  1710.                         xp = 0;
  1711.                     }
  1712.                     filelen = BUFFERS;                       /* expected or desired len to go */
  1713.                 }
  1714.  
  1715.                 if (mycode == CONDATA) {
  1716.                     if (ftpfilemode == FAMODE)
  1717.                         fcnt = Sfread (myftpdata, (char *)&xs[xp], (long) filelen);
  1718.                     else
  1719.                         fcnt = netread (myftpdata, &xs[xp], (int) filelen);
  1720.  
  1721.                     if (fcnt >= 0) {
  1722.                         filelen -= fcnt;
  1723.                         xp += fcnt;
  1724.                         translen += fcnt;
  1725.                     }
  1726.  
  1727.                     mytime = TickCount ();
  1728.                     if ((transtime + 800) < mytime) {
  1729.                         transtime = mytime;
  1730.                         if ((screens[mywindow].clientflags & MGET_STATE) == 0) {
  1731.                             sprintf (printline, "%ld bytes received.\015\013", translen);
  1732.                             i = strlen (printline);
  1733.                             parse (&screens[mywindow], (unsigned char *) &printline[0], i);
  1734.                         }
  1735.                     }
  1736.  
  1737.                     /* printf(" %d %d %d \012",filelen,xp,fcnt); n_row();  */
  1738.                     if (fcnt < 0) {
  1739.                         if (0 > MBwrite (ftp_mbfp, xs, xp)) {
  1740.                             break;
  1741.                         }
  1742.                         if (ftp_mbfp->fd != 0) {
  1743.                             MBclose (ftp_mbfp);
  1744.                         }
  1745.                         ftpfh = 0;
  1746.                     }
  1747.                     netputuev (CONCLASS, CONDATA, myport,0);
  1748.                 }
  1749.             }
  1750.         }
  1751.         /* Ouput any remaining data before closing */
  1752.         if (mycode == CONCLOSE) {
  1753.             if (xp) {
  1754.                 if (0 > MBwrite (ftp_mbfp, xs, xp))
  1755.                     netclose (myftpdata);
  1756.             }
  1757.             if ((screens[mywindow].clientflags & MGET_STATE) == 0) {
  1758.                 sprintf (printline, "%ld bytes received.\015\013", translen);
  1759.                 i = strlen (printline);
  1760.                 parse (&screens[mywindow], (unsigned char *) &printline[0], i);
  1761.             }
  1762.         }
  1763.         break;
  1764.  
  1765.         /* Waiting for "ftpdata" connection to open, display any communication from the telnet
  1766.            port. */
  1767.     case 40:
  1768.         if (mycode == CONOPEN)
  1769.             screens[mywindow].ftpstate = 41;
  1770.  
  1771.         if ((myport == myftpdata) &&
  1772.             ((screens[mywindow].clientflags & CAPTURE_DATA) != 0)) {
  1773.             captcon (myport, mywindow);
  1774.         }
  1775.         else {
  1776.             connection_status = dumpcon (myport, mywindow);
  1777.         }
  1778.         break;
  1779.  
  1780.         /* If the "ftpdata" port is open, then postpone reading and displaying any data from other
  1781.            ports once data has been received.  Otherwise, read and display data from anywhere. */
  1782.     case 41:
  1783.         if (mycode == CONDATA) {
  1784.             if ((myport == myftpdata) &&
  1785.                 ((screens[mywindow].clientflags & CAPTURE_DATA) != 0)) {
  1786.                 captcon (myport, mywindow);
  1787.             }
  1788.             else {
  1789.                 connection_status = dumpcon (myport, mywindow);
  1790.             }
  1791.             if (myport == myftpdata)
  1792.                 screens[mywindow].ftpstate = 42;
  1793.             netputuev (CONCLASS, CONDATA, myport,0);
  1794.         }
  1795.         else if (mycode == CONCLOSE) {
  1796.             screens[mywindow].ftpstate = 40;
  1797.         }
  1798.         break;
  1799.  
  1800.         /* Only data from "ftpdata" */
  1801.     case 42:
  1802.         if (mycode == CONDATA) {
  1803.             if (myport == myftpdata) {
  1804.                 if ((screens[mywindow].clientflags & CAPTURE_DATA) != 0) {
  1805.                     captcon (myport, mywindow);
  1806.                 }
  1807.                 else {
  1808.                     connection_status = dumpcon (myport, mywindow);
  1809.                 }
  1810.             }
  1811.             netputuev (CONCLASS, CONDATA, myport,0);           /* Keep port monitoring alive */
  1812.         }
  1813.         else if (mycode == CONCLOSE) {
  1814.             screens[mywindow].ftpstate = 40;
  1815.         }
  1816.         break;
  1817.  
  1818.     }                                                       /* end of switch */
  1819.  
  1820.     /* After reading from connection, if the connection is closed, reset up shop. */
  1821.     if ((mycode == CONCLOSE) || (connection_status < 0)) { /* BYU 2.4.12 */
  1822.         if (connection_status < 0)                           /* BYU 2.4.12 */
  1823.             screens[mywindow].clientflags &= ~MPUT_STATE;
  1824.         if (ftpfh > 0) {
  1825.             /* Close(ftpfh);        /* BYU LSC */
  1826.             ftpfh = 0;
  1827.         }
  1828.         if (ftp_mbfp->fd != 0)
  1829.             MBclose (ftp_mbfp);
  1830.         screens[mywindow].ftpstate = 1;
  1831.         fcnt = 0;
  1832.         if (myftpdata == myport) {
  1833.             netclose (myftpdata);
  1834.             SetPortType(myftpdata, NO_TYPE);
  1835.             screens[mywindow].ftpport = -1;
  1836.         }
  1837.         if ((screens[mywindow].clientflags & TYPE_I_ON_CLOSE) != 0) {
  1838.             screens[mywindow].clientflags = 0;
  1839.             cmd_status = ftpdo (mywindow, "TYPE I", "");
  1840.         }
  1841.  
  1842.         /* Send the next file of an MPUT */
  1843.         if ((screens[mywindow].clientflags & MPUT_STATE) != 0) {
  1844.             needanswer = TRUE;
  1845.             while (needanswer) {
  1846.                 needanswer = FALSE;
  1847.                 if (glob) {                                   /* local wildcard expansion */
  1848.                     newfile = (unsigned char *) nextname (Template, &ClientDirectoryState);    /* get next name */
  1849.                     if (newfile == NULL) {                   /* if no expansions yet */
  1850.                         if (getword ((char *) captlist, (char *) transfile)) {
  1851.                             strcpy(Template, (char *) transfile);
  1852.                             newfile = (unsigned char *) firstname (Template, TelInfo->FTPClientDirID, TelInfo->FTPClientVRefNum, &ClientDirectoryState);    /* get first name */
  1853.                             if (newfile == NULL) {           /* if no expansions */
  1854.                                 sprintf (printline, "No match for %s", transfile);
  1855.                                 ftpclient_debug_print (printline);
  1856.                             }
  1857.                         }
  1858.                     }
  1859.                 }
  1860.                 else if (getword ((char *) captlist, (char *) transfile)) {
  1861.                     newfile = transfile;
  1862.                 }
  1863.                 else
  1864.                     newfile = NULL;
  1865.  
  1866.                 if (newfile == NULL) {
  1867.                     screens[mywindow].clientflags &= ~MPUT_STATE;
  1868.                     screens[mywindow].ftpstate = 1;
  1869.                 }
  1870.                 else {
  1871. #if 1                                                       /* When prompting is fixed switch to the
  1872.                                                               code below */
  1873.                     sprintf (screens[mywindow].ftpbuf, "STOR \"%s\"", newfile);
  1874.                     cmd_status = ftpdo (mywindow, screens[mywindow].ftpbuf, "");
  1875. #else
  1876.                     if (prompt) {                           /* check */
  1877.                         sprintf (printline, "mput %s? ", newfile);
  1878.                         putstring (mywindow, printline);
  1879.                         if (ftpgets (answer, 20, 1) == ABORT) {    /* abort */
  1880.                             screens[mywindow].clientflags &= ~MPUT_STATE;
  1881.                             screens[mywindow].ftpstate = 1;
  1882.                         }
  1883.                         else if (tolower (*(stpblkp (answer))) != 'y') {
  1884.                             needanswer = TRUE;
  1885.                         }
  1886.                         else {
  1887.                             sprintf (screens[mywindow].ftpbuf, "STOR \"%s\"", newfile);
  1888.                             cmd_status = ftpdo (mywindow, screens[mywindow].ftpbuf, "");
  1889.                         }
  1890.                     }
  1891.                     else {
  1892.                         /* The Mac file may have special characters, so quote the whole thing */
  1893.                         sprintf (screens[mywindow].ftpbuf, "STOR \"%s\"", newfile);
  1894.                         cmd_status = ftpdo (mywindow, screens[mywindow].ftpbuf, "");
  1895.                     }
  1896. #endif
  1897.                 }
  1898.             }
  1899.         }
  1900.  
  1901.         if ((screens[mywindow].clientflags & MGET_STATE) != 0) {
  1902.             screens[mywindow].ftpstate = 5;                   /* BYU 3 */
  1903.             netputuev (CONCLASS, CONDATA, mytelport,0);       /* BYU 3 - Stay alive to transfer file */
  1904.         }
  1905.     }
  1906.     return (TRUE);
  1907. }
  1908.